package utstat.listeners;

import static utstat.Team.blue;
import static utstat.Team.red;
import static utstat.Type.flagCapture;
import static utstat.Type.flagDrop;
import static utstat.Type.flagGrab;
import static utstat.Type.flagReturn;

import static utstat.Type.kill;
import static utstat.Weapon.Flag;
import static utstat.listeners.FlagEventListener.State.atBase;
import static utstat.listeners.FlagEventListener.State.carried;
import static utstat.listeners.FlagEventListener.State.dropped;

import java.util.HashMap;
import java.util.Map;

import utstat.Team;
import utstat.UtEvent;
import utstat.UtEventListener;

public class FlagEventListener implements UtEventListener {

	public enum State {
		dropped, atBase, carried
	};

	private State redState = atBase;
	private State blueState = atBase;

	private int blueFlagGrabTime = 0;
	private int redFlagGrabTime = 0;
	private int blueFlagReturnTime = 0;
	private int redFlagReturnTime = 0;
	private int blueFlagCaptureTime = 0;
	private int redFlagCaptureTime = 0;
	private int blueFlagTkTime = 0;
	private int redFlagTkTime = 0;
	private int blueFlagCarrierKillTime = 0;
	private int redFlagCarrierKillTime = 0;

	private String redFlagReturner = "";
	private String blueFlagReturner = "";
	private String redFlagCapturer = "";
	private String blueFlagCapturer = "";
	private String redFlagCarrier = "";
	private String blueFlagCarrier = "";
	private String blueFlagTKer = "";
	private String redFlagTKer = "";
	private String blueFlagCarrierKiller = "";
	private String redFlagCarrierKiller = "";

	private int bluePasses = 0, redPasses = 0;

	private Map<String, Integer> fastestCaptureTimeByPlayer = new HashMap<String, Integer>();
	private int longestCapture = 0;
	private int mostPasses = 0;
	private Map<String, Integer> grabCounts = new HashMap<String, Integer>();
	private Map<String, Integer> captureCounts = new HashMap<String, Integer>();
	private Map<String, Integer> returnCounts = new HashMap<String, Integer>();
	private Map<String, Integer> hotPotatoCounts = new HashMap<String, Integer>();
	private int currentRound = -1;

	@Override
	public void processEvent(UtEvent e) {

		if (e.getRound() != currentRound) {
			nextRound();
			currentRound = e.getRound();
		}
		
		if(e.getSrc()==null) return;

		if (e.getType() == kill && e.getWeapon() == Flag) {
			int count = increment(e, hotPotatoCounts);
			if (count > 1) System.out.println(e.getSrc() + "'s " + nth(count) + " hot potato!");
		}

		if (e.getType() == kill) {
			if (e.getTeam() == red && e.getDest().equals(blueFlagCarrier))  { blueFlagTKer = e.getSrc(); blueFlagTkTime = e.getTime();}
			if (e.getTeam() == blue  && e.getDest().equals(redFlagCarrier)) { redFlagTKer = e.getSrc(); redFlagTkTime = e.getTime();}
			if (e.getTeam() == red && e.getDest().equals(redFlagCarrier))   { redFlagCarrierKiller = e.getSrc(); redFlagCarrierKillTime =e.getTime();}
			if (e.getTeam() == blue  && e.getDest().equals(blueFlagCarrier)) { blueFlagCarrierKiller = e.getSrc(); blueFlagCarrierKillTime =e.getTime();}
			if(e.getDest().equals(redFlagCarrierKiller)) { redFlagCarrierKiller = ""; redFlagCarrierKillTime = 0; }
			if(e.getDest().equals(blueFlagCarrierKiller)) { blueFlagCarrierKiller = ""; blueFlagCarrierKillTime = 0; }
		}

		if (e.getType() == kill && e.getTime() - (e.getEnemyTeam() == blue ? blueFlagCaptureTime : redFlagCaptureTime) < 2
				&& e.getDest().equals(e.getEnemyTeam() == blue ? blueFlagCapturer : redFlagCapturer)) {
			System.out.println("so close! " + e.getSrc() + " killed " + e.getDest() + " " + (e.getTime() - (e.getEnemyTeam() == blue ? blueFlagCaptureTime : redFlagCaptureTime))
					+ " seconds after he captured the blue flag!");
		}

		if (e.getType() == flagGrab) {

			if (e.getTeam() == red) {
				if (redState == atBase) {
					redFlagGrabTime = e.getTime();
					redPasses = 0;
				}
				if (redState == dropped) redPasses++;
				redState = carried;
				redFlagCarrier = e.getSrc();

			}
			if (e.getTeam() == blue) {

				if (blueState == atBase) {
					blueFlagGrabTime = e.getTime();
					bluePasses = 0;
				}
				if (blueState == dropped) {
					bluePasses++;
				}
				blueState = carried;
				blueFlagCarrier = e.getSrc();
			}
			// System.out.println(e.getTeam() + " grabbed by " + e.getSrc());

			Integer grabCount = grabCounts.get(e.getSrc());
			if (grabCount == null) grabCount = 0;
			grabCount++;
			grabCounts.put(e.getSrc(), grabCount);
		}

		if (e.getType() == flagCapture) {

			redState = atBase;
			blueState = atBase;
			redFlagCarrier = "";
			blueFlagCarrier = "";
			redFlagTkTime=0;
			redFlagTKer="";
			blueFlagTkTime=0;
			blueFlagTKer="";

			Team flagCaptured = e.getTeam() == blue ? red : blue;
			int time = 0, passes = 0;
			if (flagCaptured == red) {
				time = e.getTime() - redFlagGrabTime;
				passes = redPasses;
				redFlagCapturer = e.getSrc();
				redFlagCaptureTime = e.getTime();
				if(e.getTime()-blueFlagCarrierKillTime<20 && redFlagCapturer.equals(blueFlagCarrierKiller)) System.out.println(e.getSrc()+"  is a one-man army!");
			}
			if (flagCaptured == blue) {
				time = e.getTime() - blueFlagGrabTime;
				passes = bluePasses;
				blueFlagCapturer = e.getSrc();
				blueFlagCaptureTime = e.getTime();
				if(e.getTime()-redFlagCarrierKillTime<20 && blueFlagCapturer.equals(redFlagCarrierKiller)) System.out.println(e.getSrc()+"  is a one-man army!");
				
			}

			// System.out.println(e.getTime()+" "+flagCaptured + " captured by " + e.getSrc() + " in " + time + " seconds");

			Integer previousFastestTime = fastestCaptureTimeByPlayer.get(e.getSrc());
			if (previousFastestTime == null) previousFastestTime = time;
			if (previousFastestTime >= time) fastestCaptureTimeByPlayer.put(e.getSrc(), time);
			if (previousFastestTime > time) System.out.println(e.getSrc() + " broke his fastest capture record of " + previousFastestTime + " by " + (previousFastestTime - time) + " seconds!");
			if (time > longestCapture) {
				System.out.println(e.getTeam() + " broke the longest capture record of " + longestCapture + " by " + (time - longestCapture) + " seconds!");
				longestCapture = time;
			}
			if (passes > mostPasses) {
				System.out.println(e.getTeam() + " scored with a record number of " + passes + " passes");
				mostPasses = passes;
			}

			int returnTime = flagCaptured == blue ? redFlagReturnTime : blueFlagReturnTime;
			String returner = flagCaptured == blue ? redFlagReturner : blueFlagReturner;
			int returnToCaptureTime = e.getTime() - returnTime;
			if (returnToCaptureTime > 0 && returnToCaptureTime < 2 && !returner.equals(e.getSrc()) && returner != null) System.out.println(returner + " -> " + e.getSrc() + " combo!");

			Integer captureCount = captureCounts.get(e.getSrc());
			if (captureCount == null) captureCount = 0;
			captureCount++;
			captureCounts.put(e.getSrc(), captureCount);
		}

		if (e.getType() == flagReturn) {
			
			if (e.getTeam() == red) {
				redFlagReturnTime = e.getTime();
				redFlagReturner = e.getSrc();
				redState = atBase;
				redFlagCarrier = "";
				if(e.getTime()-redFlagTkTime<10) System.out.println(redFlagTKer+"'s incompetence cost the red team a capture!");
				redFlagTkTime=0;
				redFlagTKer="";
			}
			if (e.getTeam() == blue) {
				blueFlagReturnTime = e.getTime();
				blueFlagReturner = e.getSrc();
				blueState = atBase;
				redFlagCarrier = "";
				if(e.getTime()-blueFlagTkTime<10) System.out.println(blueFlagTKer+"'s incompetence cost the blue team a capture!");
				blueFlagTkTime=0;
				blueFlagTKer="";
			}
			// System.out.println(e.getTeam() + " returned by " + e.getSrc() + " after " + time + " seconds");

			Integer returnCount = returnCounts.get(e.getSrc());
			if (returnCount == null) returnCount = 0;
			returnCount++;
			returnCounts.put(e.getSrc(), returnCount);
			

		}

		if (e.getType() == flagDrop) {

			int time = 0;
			if (e.getTeam() == red) {
				redState = dropped;
				time = e.getTime() - redFlagGrabTime;
				redFlagCarrier = "";
			}
			if (e.getTeam() == blue) {
				blueState = dropped;
				time = e.getTime() - blueFlagGrabTime;
				blueFlagCarrier = "";
			}
			// System.out.println(e.getTeam() + " dropped by " + e.getSrc() + " after " + time + " seconds");
		}

	}

	private int increment(UtEvent e, Map<String, Integer> countMap) {
		Integer count = countMap.get(e.getSrc());
		if (count == null) count = 0;
		count++;
		countMap.put(e.getSrc(), count);
		return count;
	}

	public String nth(int num) {
		String n = ("" + num);
		n = n.substring(n.length() - 1);
		if (n.equals("1")) return num + "st";
		if (n.equals("2")) return num + "nd";
		if (n.equals("3")) return num + "rd";
		return num + "th";
	}

	@Override
	public String getIntestingFact(String player) {
		return "You are all failures!";
	}

	public void nextRound() {
		System.out.println("------");
		redState = atBase;
		blueState = atBase;
		blueFlagGrabTime = 0;
		redFlagGrabTime = 0;
		bluePasses = 0;
		redPasses = 0;
		blueFlagReturnTime = 0;
		redFlagReturnTime = 0;
		blueFlagCaptureTime = 0;
		redFlagCaptureTime = 0;
		redFlagReturner = "";
		blueFlagReturner = "";
		redFlagCapturer = "";
		blueFlagCapturer = "";
		redFlagCarrier = "";
		blueFlagCarrier = "";
	}

}
